﻿#include "FITKAbaqusHDF5AdaptorLoad.h"

#include "FITK_Kernel/FITKCore/FITKVec3D.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"

#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Writer.h"

#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractLoad.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadConcentratedForce.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadPressure.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadMoment.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadBodyForce.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaLoadGravity.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepManager.h"

#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"

namespace IO
{
    QString FITKAbaqusHDF5AdaptorLoad::getAdaptorClass()
    {
        return "FITKAbaqusHDF5AdaptorLoad";
    }

    void FITKAbaqusHDF5AdaptorLoad::setDataCase(AbaqusData::FITKDataCase* caseData)
    {
        _caseData = caseData;
    }


    bool FITKAbaqusHDF5AdaptorLoad::adaptR()
    {
        auto load = dynamic_cast<Interface::FITKAbaAbstractLoad*>(_dataObj);
        if (!_reader || !load || !_h5Group || !_caseData || !_caseData->getLoadManager()) return false;
        bool isR = true;
        isR &= readLoad(load, *_h5Group);
        return isR;
    }

    bool FITKAbaqusHDF5AdaptorLoad::adaptW()
    {
        auto load = dynamic_cast<Interface::FITKAbaAbstractLoad*>(_dataObj);
        if (!_writer || !load || !_h5Group || !_caseData || !_caseData->getLoadManager()) return false;
        bool isW = true;
        isW &= writeLoad(load, *_h5Group);
        return isW;
    }

    bool FITKAbaqusHDF5AdaptorLoad::readLoad(Interface::FITKAbaAbstractLoad* load, H5::Group& h5Group)
    {
        if (!load || !_caseData) return false;
        bool isR = true;
        bool isValid = false;

        //读取基础信息
        isR &= readNDataObject(load, h5Group);
        auto stepManager = _caseData->getStepManager();
        auto loadType = load->getLoadType();
        //读取不同分析步的输出 不读取Init Step
        for (int i = 1; i < stepManager->getDataCount(); ++i)
        {
            auto step = stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();
            if (!h5Group.nameExists(std::to_string(stepID))) return false;
            auto childH5Group = h5Group.openGroup(std::to_string(stepID));

            //FITKAbaStepRelatedDataObject
            int CreatedStep = readIntAttribute(childH5Group, "CreatedStep");
            load->setCreatedStep(CreatedStep);
            int DeactiveStep = readIntAttribute(childH5Group, "DeactiveStep");
            load->setDeactiveStep(DeactiveStep);
            bool ActiveState = readBoolAttribute(childH5Group, "ActiveState");
            load->setActiveState(ActiveState);
            //FITKBoundaryLocation 
            int ModelID = readIntAttribute(childH5Group, "ModelID");
            load->setModel(ModelID);
            int ComponentID = readIntAttribute(childH5Group, "ComponentID");
            load->setComponent(ComponentID);

            if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::BodyForce)
            {
                isR &= readLoadBodyForce(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::ConcentratedForce)
            {
                isR &= readLoadConcentratedForce(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::Gravity)
            {
                isR &= readLoadGravity(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::Moment)
            {
                isR &= readLoadMoment(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::Pressure)
            {
                isR &= readLoadPressure(load, stepID, childH5Group);
            }
            else
            {
                return false;
            }
        }
        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::readLoadConcentratedForce(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadConcentratedForce* cLoad = dynamic_cast<Interface::FITKAbaLoadConcentratedForce*>(load);
        auto loadManager = _caseData->getLoadManager();
        if (!cLoad || !loadManager) return false;

        double CF1 = readDoubleAttribute(h5Group, "CF1");
        cLoad->setCF1(CF1, stepID);
        double CF2 = readDoubleAttribute(h5Group, "CF2");
        cLoad->setCF2(CF2, stepID);
        double CF3 = readDoubleAttribute(h5Group, "CF3");
        cLoad->setCF3(CF3, stepID);

        bool FlowNodalRotation = readBoolAttribute(h5Group, "FlowNodalRotation");
        cLoad->setFlowNodalRotation(FlowNodalRotation);
        int AnalyticalFieldId = readIntAttribute(h5Group, "AnalyticalFieldId");
        cLoad->setAnalyticalFieldId(AnalyticalFieldId);
        int CsysId = readIntAttribute(h5Group, "CsysId");
        cLoad->setCsysId(CsysId);
        int AmplitudeId = readIntAttribute(h5Group, "AmplitudeId");
        cLoad->setAmplitudeId(AmplitudeId);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::readLoadMoment(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadMoment* cLoadMoment = dynamic_cast<Interface::FITKAbaLoadMoment*>(load);
        if (!cLoadMoment) return false;

        double CM1 = readDoubleAttribute(h5Group, "CM1");
        cLoadMoment->setCM1(CM1, stepID);
        double CM2 = readDoubleAttribute(h5Group, "CM2");
        cLoadMoment->setCM2(CM2, stepID);
        double CM3 = readDoubleAttribute(h5Group, "CM3");
        cLoadMoment->setCM3(CM3, stepID);
        int AmplitudeId = readIntAttribute(h5Group, "AmplitudeId");
        cLoadMoment->setAmplitudeId(AmplitudeId, stepID);
        int AnalyticalFieldId = readIntAttribute(h5Group, "AnalyticalFieldId");
        cLoadMoment->setAnalyticalFieldId(AnalyticalFieldId);
        int CsysId = readIntAttribute(h5Group, "CsysId");
        cLoadMoment->setCsysId(CsysId);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::readLoadPressure(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadPressure* cLoadPressure = dynamic_cast<Interface::FITKAbaLoadPressure*>(load);
        if (!cLoadPressure) return false;

        double Pressure = readDoubleAttribute(h5Group, "Pressure");
        cLoadPressure->setPressure(Pressure, stepID);
        int AmplitudeId = readIntAttribute(h5Group, "AmplitudeId");
        cLoadPressure->setAmplitudeId(AmplitudeId, stepID);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::readLoadBodyForce(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadBodyForce* dloadBodyForce = dynamic_cast<Interface::FITKAbaLoadBodyForce*>(load);
        if (!dloadBodyForce) return false;

        double Component1 = readDoubleAttribute(h5Group, "Component1");
        dloadBodyForce->setComponent1(Component1, stepID);
        double Component2 = readDoubleAttribute(h5Group, "Component2");
        dloadBodyForce->setComponent2(Component2, stepID);
        double Component3 = readDoubleAttribute(h5Group, "Component3");
        dloadBodyForce->setComponent3(Component3, stepID);
        int AmplitudeId = readIntAttribute(h5Group, "AmplitudeId");
        dloadBodyForce->setAmplitudeId(AmplitudeId, stepID);
        int AnalyticalFieldId = readIntAttribute(h5Group, "AnalyticalFieldId");
        dloadBodyForce->setAnalyticalFieldId(AnalyticalFieldId);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::readLoadGravity(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadGravity* loadGravity = dynamic_cast<Interface::FITKAbaLoadGravity*>(load);
        if (!loadGravity) return false;
        bool WholeModel = readBoolAttribute(h5Group, "WholeModel");
        loadGravity->setWholeModel(WholeModel);
        return readLoadBodyForce(loadGravity, stepID, h5Group);
    }


    bool FITKAbaqusHDF5AdaptorLoad::writeLoad(Interface::FITKAbaAbstractLoad* load, H5::Group& h5Group)
    {
        if (!load || !_caseData) return false;
        bool isW = true;
        bool isValid = false;

        std::string groupName = createParentAttribute(load, h5Group);
        if (groupName.empty())return false;
        _h5CreateGroup = h5Group.createGroup(groupName);

        //枚举转换字符 写出类型
        auto loadType = load->getLoadType();
        Core::FITKEnumTransfer<Interface::FITKAbaAbstractLoad::FITKAbaLoadType> fitkLoadTypeTrafer;
        auto sType = fitkLoadTypeTrafer.toStrting(loadType, isValid);
        if (!isValid) return false;
        writeStrAttribute(_h5CreateGroup, "Type", sType.toStdString());

        auto stepManager = _caseData->getStepManager();

        //写出不同分析步的输出 不写出Init Step
        for (int i = 1; i < stepManager->getDataCount(); ++i)
        {
            auto step = stepManager->getDataByIndex(i);
            int stepID = step->getDataObjectID();
            auto childH5Group = _h5CreateGroup.createGroup(std::to_string(stepID));

            //FITKAbaStepRelatedDataObject
            int CreatedStep = load->getCreatedStep();
            writeIntAttribute(childH5Group, "CreatedStep", &CreatedStep);
            int DeactiveStep = load->getDeactiveStep();
            writeIntAttribute(childH5Group, "DeactiveStep", &DeactiveStep);
            //FITKAbaAbstractLoad
            bool ActiveState = load->getActiveState();
            writeBoolAttribute(childH5Group, "ActiveState", &ActiveState);
            //FITKBoundaryLocation 
            int ModelID = load->getModelID();
            writeIntAttribute(childH5Group, "ModelID", &ModelID);
            int ComponentID = load->getComponentID();
            writeIntAttribute(childH5Group, "ComponentID", &ComponentID);

            if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::BodyForce)
            {
                isW &= writeLoadBodyForce(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::ConcentratedForce)
            {
                isW &= writeLoadConcentratedForce(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::Gravity)
            {
                isW &= writeLoadGravity(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::Moment)
            {
                isW &= writeLoadMoment(load, stepID, childH5Group);
            }
            else if (loadType == Interface::FITKAbaAbstractLoad::FITKAbaLoadType::Pressure)
            {
                isW &= writeLoadPressure(load, stepID, childH5Group);
            }
            else
            {
                return false;
            }
        }
        //写出基础信息
        isW &= writeNDataObject(load, _h5CreateGroup);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::writeLoadConcentratedForce(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadConcentratedForce* cLoad = dynamic_cast<Interface::FITKAbaLoadConcentratedForce*>(load);
        auto loadManager = _caseData->getLoadManager();
        if (!cLoad || !loadManager) return false;

        double CF1 = cLoad->getCF1(stepID);
        writeDoubleAttribute(h5Group, "CF1", &CF1);
        double CF2 = cLoad->getCF2(stepID);
        writeDoubleAttribute(h5Group, "CF2", &CF2);
        double CF3 = cLoad->getCF3(stepID);
        writeDoubleAttribute(h5Group, "CF3", &CF3);
        bool FlowNodalRotation = cLoad->getFlowNodalRotation();
        writeBoolAttribute(h5Group, "FlowNodalRotation", &FlowNodalRotation);
        int AnalyticalFieldId = cLoad->getAnalyticalFieldId();
        writeBoolAttribute(h5Group, "AnalyticalFieldId", &AnalyticalFieldId);
        int CsysId = cLoad->getCsysId();
        writeBoolAttribute(h5Group, "CsysId", &CsysId);
        int AmplitudeId = cLoad->getAmplitudeId();
        writeIntAttribute(h5Group, "AmplitudeId", &AmplitudeId);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::writeLoadMoment(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadMoment* cLoadMoment = dynamic_cast<Interface::FITKAbaLoadMoment*>(load);
        if (!cLoadMoment) return false;

        double CM1 = cLoadMoment->getCM1(stepID);
        writeDoubleAttribute(h5Group, "CM1", &CM1);
        double CM2 = cLoadMoment->getCM2(stepID);
        writeDoubleAttribute(h5Group, "CM2", &CM2);
        double CM3 = cLoadMoment->getCM3(stepID);
        writeDoubleAttribute(h5Group, "CM3", &CM3);
        int AmplitudeId = cLoadMoment->getAmplitudeId(stepID);
        writeIntAttribute(h5Group, "AmplitudeId", &AmplitudeId);
        int AnalyticalFieldId = cLoadMoment->getAnalyticalFieldId();
        writeIntAttribute(h5Group, "AnalyticalFieldId", &AnalyticalFieldId);
        int CsysId = cLoadMoment->getCsysId();
        writeIntAttribute(h5Group, "CsysId", &CsysId);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::writeLoadPressure(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadPressure* cLoadPressure = dynamic_cast<Interface::FITKAbaLoadPressure*>(load);
        if (!cLoadPressure) return false;

        double Pressure = cLoadPressure->getPressure(stepID);
        writeDoubleAttribute(h5Group, "Pressure", &Pressure);
        int AmplitudeId = cLoadPressure->getAmplitudeId();
        writeIntAttribute(h5Group, "AmplitudeId", &AmplitudeId);
        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::writeLoadBodyForce(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadBodyForce* dloadBodyForce = dynamic_cast<Interface::FITKAbaLoadBodyForce*>(load);
        if (!dloadBodyForce) return false;

        double Component1 = dloadBodyForce->getComponent1(stepID);
        writeDoubleAttribute(h5Group, "Component1", &Component1);
        double Component2 = dloadBodyForce->getComponent2(stepID);
        writeDoubleAttribute(h5Group, "Component2", &Component2);
        double Component3 = dloadBodyForce->getComponent3(stepID);
        writeDoubleAttribute(h5Group, "Component3", &Component3);
        int AmplitudeId = dloadBodyForce->getAmplitudeId();
        writeIntAttribute(h5Group, "AmplitudeId", &AmplitudeId);
        int AnalyticalFieldId = dloadBodyForce->getAnalyticalFieldId();
        writeIntAttribute(h5Group, "AnalyticalFieldId", &AnalyticalFieldId);

        return true;
    }

    bool FITKAbaqusHDF5AdaptorLoad::writeLoadGravity(Interface::FITKAbaAbstractLoad* load, int stepID, H5::Group& h5Group)
    {
        Interface::FITKAbaLoadGravity* loadGravity = dynamic_cast<Interface::FITKAbaLoadGravity*>(load);
        if (!loadGravity) return false;
        bool WholeModel = loadGravity->isWholeModel();
        writeBoolAttribute(h5Group, "WholeModel", &WholeModel);
        return writeLoadBodyForce(loadGravity, stepID, h5Group);
    }

}
